﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ExpressionEvaluator.Expceptions;
using System.Linq.Expressions;

namespace ExpressionEvaluator.BuilderTreeNode
{
	/// <summary>
	/// Node containing indexer expression.
	/// </summary>
	internal class IndexerNode : OpaqueExpressionNode
	{
		/// <summary>
		/// Gets or sets the start bracket.
		/// </summary>
		/// <value>The start bracket.</value>
		public CodeBlock StartBracket
		{
			get;
			set;
		}

		/// <summary>
		/// Gets or sets the end bracket.
		/// </summary>
		/// <value>The end bracket.</value>
		public CodeBlock EndBracket
		{
			get;
			set;
		}

		/// <summary>
		/// Gets the parent expression for expression.
		/// </summary>
		/// <param name="parent">The parent expression.</param>
		/// <param name="tree">The tree.</param>
		/// <returns>Expression for this node.</returns>
		public override System.Linq.Expressions.Expression GetParentExpression(System.Linq.Expressions.Expression parent, BuilderTree tree)
		{
			// simple indexer
			if (Nodes.Count == 1)
			{
				return Expression.ArrayIndex(parent, Nodes[0].GetExpression(tree));
			}
			// advanced indexer
			else if (Nodes.Count > 1)
			{
				List<Expression> indexParameters = new List<Expression>();
				List<Type> parameterTypes = new List<Type>();
				foreach (BuilderTreeNodeBase node in Nodes)
				{
					Expression nodeExpression = node.GetExpression(tree);
					indexParameters.Add(nodeExpression);
					parameterTypes.Add(nodeExpression.Type);
				}
				return Expression.ArrayIndex(parent, indexParameters);
			}
			else
			{
				throw new EvalException("Indexer should have indexes!", Idents[0]);
			}
		}

		/// <summary>
		/// Gets the parent expression for type.
		/// </summary>
		/// <param name="parent">The parent type.</param>
		/// <param name="tree">The tree.</param>
		/// <returns>Expression for this node.</returns>
		public override Expression GetParentExpression(Type parent, BuilderTree tree)
		{
			throw new EvalException("Static indexer not supported!", StartBracket);
		}

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		public override string ToString()
		{
			StringBuilder result = new StringBuilder();
			result.Append("[");
			for (int i = 0; i < Nodes.Count; ++i)
			{
				if (i > 0)
				{
					result.Append(",");
				}
				result.Append(Nodes[i].ToString());
			}
			result.Append("]");
			return result.ToString();
		}
	}
}
